function Item() {
	this.id = null;
	this.label = null;
	this.key = null;
	this.parent_key = null;
	this.start_date = null;
	this.end_date = null;
	this.objective = null;
	this.owner_validation = null;
	this.adviser_validation = null;
	this.validation_comment = null;
	this.objective_needs = null;
	this.objective_contacts = null;
	this.project_id = null;
	this.topic_id = null;
	this.step_id = null;
	this.item_type = null;
	this.checked = false;
}

Item.ckeditor_options = {};

Item.dialog_options = {width:'75%', height:'400', minHeight:'400', autoOpen: true };
Item.auto_open_dialog = false;

Item.buildItems = function() {
	var arr = [];
	var project_id = $("#project_id").attr('value');
	
	Item.root.find('li').each(function(index, item){
		var i = new Item();
		var key = item.id;
		item=$(item);
		var baseId = Item.baseId+"_"+key;
		i.id = $("#"+baseId+"_id").attr('value');
		i.label = item.children('.label').text();
		i.key = key;
		i.parent_key = $("#"+baseId+"_parent_key").attr('value');
		i.start_date = item.children('.item').children('.user_inputs').children('.start_date').attr('value');
		i.end_date = item.children('.item').children('.user_inputs').children('.end_date').attr('value');
		i.objective = $("#"+baseId+"_objective").is(':checked');
		i.adviser_validation = $("#"+baseId+"_adviser_validation").is(':checked');
		i.owner_validation = $("#"+baseId+"_owner_validation").is(':checked');
		i.objective_needs = $("#"+baseId+"_objective_needs").text();
		i.objective_contacts = $("#"+baseId+"_objective_contacts").text();
		i.project_id = project_id;
		i.checked = ($("#"+baseId+"_checked").length == 0 || $("#"+baseId+"_checked").attr('value') != 0);
		
		if (key.substr(0,4) == "step") {
			i.step_id = key.substr(5);
		} else {
			i.topic_id = key.substr(6);
		}
		
		arr.push(i);
	});
	
	return arr;
};

Item.inProgress = false;

Item.sendInBackground = function(url) {
	if (Item.inProgress)
		return;
	
	Item.inProgress = true;
	
	Logger.info('send data '+url);
	$.ajax({
		  type: 'POST',
		  url: url,
		  data: { items : Item.buildItems() },
		  success: function (data, textStatus, jqXHR) {
			  Logger.info('Data saved '+textStatus+" ");
		  },
		  error: function (jqXHR, textStatus, errorThrown) {
			  Logger.info('Could not save '+textStatus);
		  },
		  dataType: 'json'
		});
	
	// Logger.info(JSON.stringify(Item.buildItems()));
	
	Item.inProgress = false;	
};


/**
 * Prefix for all id.
 */
Item.baseId = null;
/**
 * Default date format used to parse date values.
 */
Item.dateFormat = null;
Item.root = null;
Item.steps = null;
Item.previous = new Array();

Item.adviser_validation_image='/images/confirm.png';
Item.owner_validation_image = '/images/progress.gif';
Item.objective_image = '/images/target.png';
Item.comment_image = '/images/comment.png';

Item.init = function(baseId, dateFormat, id, ckeditor_options) {
	Logger.info(" ===== Initialisation des items =====");
	Item.ckeditor_options  = ckeditor_options;
	Item.baseId = baseId;
	Item.dateFormat = dateFormat;
	Item.root = $("#"+id);
	Item.steps = Item.root.children('ul').children('li');
	
	// 1) on masque les zones de commentaires
	Logger.info("> on masque les zones de commentaires"); 
	Item.root.find('.validation_area, .objective_area, .comment_area').hide();
	Item.root.find('.validation_link').each(function(index, item){
		var icon = "images/edit.png";
		var cbs = $(this).parent().children('.validation_cb');
		if (cbs.is(':disabled') || !cbs.is(':checked')) {
			var icon = "images/empty.png";
		}
		$(item).prepend("<img src='"+icon+"' alt='"+$(item).attr('alt')+"' width='16' height='16'></img>");
	});
	
	Item.root.find('.objective_link').each(function(index, item){
		var icon = "images/edit.png";
		var cbs = $(this).parent().children('.objective_cb');
		if (cbs.is(':disabled') || !cbs.is(':checked')) {
			var icon = "images/empty.png";
		}
		$(item).prepend("<img src='"+icon+"' alt='"+$(item).attr('alt')+"' width='16' height='16'></img>");
	});
	
	Item.root.find('.validation_cb').click(function(event){
		var icon = "images/edit.png";
		var cbs = $(this).parent().children('.validation_cb');
		if (cbs.is(':disabled') || !cbs.is(':checked')) {
			var icon = "images/empty.png";
		}
		$(this).parent().children('.validation_link').children("img").attr("src", icon);
	});
	
	Item.root.find('.objective_cb').click(function(event){
		var icon = "images/edit.png";
		var cbs = $(this).parent().children('.objective_cb');
		if (cbs.is(':disabled') || !cbs.is(':checked')) {
			var icon = "images/empty.png";
		}
		$(this).parent().children('.objective_link').children("img").attr("src", icon);
	});
	
	// 2) ajoute une icone pour afficher les cases à cocher
	Logger.info("> ajoute une icone pour afficher les cases à cocher"); 
	Item.root.find(".user_inputs").each(function(index, input){
		cbs = $(this).findParent('.item').children('.comment_area').find('input[type=checkbox]').filter(':checked');
		var dlg_link = $('<a class="dlg_link"><img src="'+Item.comment_image+'" /></a>');
		Item.set_validation_image(dlg_link.find("img"), cbs);
		if ($(input).children().length > 0) {
			$(input).children(":last").after(dlg_link);
		} else {
			$(input).html(dlg_link);
		}
	});
	Item.root.find(".dlg_link").live('click', function(event){
/*		var cmt_area = "#comment_"+$(this).findParent('li').attr('id');;
		cmt_area = $(cmt_area).dialog('open');
		
		cmt_area.find('.owner_validation').siblings('.validation_area').find('textarea').ckeditor(Item.ckeditor_options);
		cmt_area.find('.adviser_validation').siblings('.validation_area').find('textarea').ckeditor(Item.ckeditor_options);
		cmt_area.find('.objective').siblings('.objective_area').find('textarea').ckeditor(Item.ckeditor_options);
		*/
		var cmt_area = $(this).findParent('.item').children(".comment_area").slideToggle();
		cmt_area.find('.owner_validation').filter(':checked').not(':disabled').siblings('.validation_area')/*.dialog(jQuery.extend({autoOpen:false}, Item.dialog_options))*/.show().find('textarea').ckeditor(Item.ckeditor_options);
		cmt_area.find('.adviser_validation').filter(':checked').not(':disabled').siblings('.validation_area')/*.dialog(jQuery.extend({autoOpen:false}, Item.dialog_options))*/.show().find('textarea').ckeditor(Item.ckeditor_options);
		cmt_area.find('.objective').filter(':checked').not(':disabled').siblings('.objective_area')/*.dialog(jQuery.extend({autoOpen:false}, Item.dialog_options))*/.show().find('textarea').ckeditor(Item.ckeditor_options);
	 });
	
	// 3) propage la validation du conseiller, du porteur et des objectifs
	Logger.info("> propage la validation du conseiller, du porteur et des objectifs"); 
	Item.bind_validation(".validation_cb", "validation_comment", ".owner_validation");
	Item.bind_validation(".validation_cb", "validation_comment", ".adviser_validation");
	Item.bind_validation(".objective_cb", "objective_comments", ".objective");
	
	Item.steps.children('.item').children('.label').each(function (index, item) {
		if ($(item).findParent('li').children('ul').children('li').length > 0) {
			var v = $(item).html()+"<a class='collapse_link'><img src='images/collapse.png' alt='Expand/Collapse' /></a>";  
			$(item).html(v); 
		}
	});
	Item.root.find(".collapse_link").live('click', function(event){
		$(this).findParent('li').children('ul').slideToggle('fast', function(event){
			img = $(this).findParent('li').find(".collapse_link").children('img');
			if ($(this).is(':visible')) {
				img.attr('src', 'images/collapse.png');
			} else {
				img.attr('src', 'images/expand.png');
			}
		});
	});
	
	
	// 4) Les dates de début et de fin
	Logger.info("> Bind des événements pour la date de début");
	Item.root.find(".start_date").focus(function(event){
		Item.save(this);
	}).change(function(event){
		var item = $(this).findParent('li');
		var prev = Item.previous[this.id];
		var date = DateUtils.parse(Item.dateFormat, event.target.value);
		if (!$(this).setStartDate(event.target.value)) {
			$(this).revertItem();
			return;
		}
		
		// on prend tous les enfants qui ont une date de début identique
		var children = item.find('li').find('.start_date').beforeDate(prev);
		var update = children.saveItem().setStartDate(event.target.value);
		if (!update) {
			children.revertItem();
			$(this).revertItem();
			return;
		}
		
		// on essaye de mettre à jour le parent
		var parent = item.findParent('li').start_date();
		update = true;
		while (parent.length > 0 && update) {
			// on cherche la date de début théo du parent. si elle est
			// différente de l'actuelle, on remplace
			var minDate = parent.findParent('li').children('ul').minDate(".start_date", Item.dateFormat);
			if (parent.attr('value') != minDate) {
				children = children.add(parent);
				update = parent.saveItem().setStartDate(minDate);
				parent = parent.findParent('li').findParent('li').start_date();
			} else {
				parent = new Array();
			}
		}
		if (!update) {
			children.revertItem();
			$(this).revertItem();
			return;
		}
		children.commitItem();
		$(this).commitItem();
	});
	Logger.info("> Bind des événements pour la date de fin");
	Item.root.find(".end_date").focus(function(event){
		Item.save(this);
	}).change(function(event){
		var item = $(this).findParent('li');
		var prev = Item.previous[this.id];
		var date = DateUtils.parse(Item.dateFormat, event.target.value);
		if (!$(this).setEndDate(event.target.value)) {
			$(this).revertItem();
			return;
		}
		
		var children = item.find('li').find('.end_date').afterDate(prev);
		var update = children.saveItem().setEndDate(event.target.value);
		if (!update) {
			children.revertItem();
			$(this).revertItem();
			return;
		}
		
		// on essaye de mettre à jour le parent
		var parent = item.findParent('li').end_date();
		update = true;
		while (parent.length > 0 && update) {
			// on cherche la date de fin théo du parent. si elle est différente
			// de l'actuelle, on remplace
			var maxDate = parent.findParent('li').children('ul').maxDate(".end_date", Item.dateFormat);
			if (parent.attr('value') != maxDate) {
				children = children.add(parent);
				update = parent.saveItem().setEndDate(maxDate);
				parent = parent.findParent('li').findParent('li').end_date();
			} else {
				parent = new Array();
			}
		}
		if (!update) {
			children.revertItem();
			$(this).revertItem();
			return;
		}
		
		// on décalle tous les autres items.
		var parent = $(item).findParent('[id^=step_]').end_date();
		if (parent.length == 0 && $(item).is('[id^=step_]'))
			var parent = $(item).end_date();
		if (parent.length > 0 && Item.previous[parent.attr('id')] != null && Item.previous[parent.attr('id')] != undefined) {
			// la date de fin de l'étape a été mise à jour à priori
			prev = DateUtils.parse(Item.dateFormat, Item.previous[parent.attr('id')]);
			var nb = DateUtils.daysDiff(date, prev);
			children.add(parent.findParent('li').nextAll().find('.start_date, .end_date').addDays(Item.dateFormat, nb));
		}

		children.commitItem();
		$(this).commitItem();
	});
	
	Logger.info("> Ajout des cases de sélection de l'arbre.");
	Item.root.find('.cb_select_item').before('<div class="checkbox unchecked"><a class="cb_link"><img src="/images/empty.png" width="18" height="16" /></a></div>').each(function(index, item){
		if (item.type != 'hidden') {
			var value = "0";
			if ($(item).is(':checked')) value = "1";
			item.type = 'hidden';
			item.value = value;
			Logger.info("["+id+"] update item "+item.id+". set type=hidden / value="+item.value);
		}
		var cb = $(item).siblings('.checkbox');
		Logger.info("["+id+"] update item "+item.id+" (value="+item.value+")");
		if (item.value == "1") {
			cb.removeClass('unchecked undetermined').addClass('checked');
		}
	});
	
	Logger.info("> Mise à jour des cases parentes");
	Item.root.find('ul').findParent('li').children('.item').children('.checkbox').each(function (index, item) {
		$(item).updateState();
	});
	
	Item.root.find(".cb_link").live('click', function(event){
		cb = $(this).findParent('div');
		if (cb.hasClass('checked')) { 
			cb.unchecked(true);
		} else {
			cb.checked(true);
		}
		
		cb.parents('li').children('.item').children('.checkbox').not(cb).updateState();
	});

	Logger.info("Ajout gestionnaire affichage popup.");
	Item.root.find('.validation_link').click(function(event){
		var cbs = $(this).parent().children('.validation_cb');
		if (!cbs.is(':disabled') && cbs.is(':checked')) {
			$('#validation_comment_'+$(this).findParent('li').attr('id'))/*.dialog(Item.dialog_options)*/.toggle().find('textarea').each(function (index, item){
				CKEDITOR.replace(item.name, Item.ckeditor_options);
			});
			//$('#validation_comment_'+$(this).findParent('li').attr('id'))/*.dialog(Item.dialog_options)*/.show().find('textarea').ckeditor(Item.ckeditor_options);
		}
	});
	Item.root.find('.objective_link').click(function(event){
		var cbs = $(this).parent().children('.objective_cb');
		if (!cbs.is(':disabled') && cbs.is(':checked')) {
			//$('#objective_comment_'+$(this).findParent('li').attr('id')).dialog(Item.dialog_options).find('textarea').ckeditor(Item.ckeditor_options);
			$('#objective_comment_'+$(this).findParent('li').attr('id'))/*.dialog(Item.dialog_options)*/.toggle().find('textarea').each(function (index, item){
				CKEDITOR.replace(item.name, Item.ckeditor_options);
			});
		}
	});
	
	Logger.info(" ===== Initialisation  terminée =====");
};

Item.bind_validation = function(cb, area, type) {
	Item.root.find(type).click(function (event) {
		var parent = $(this).parent();
		if (parent.children(cb).is(":checked")) {
			var tmp = $('#' + area+ '_'+$(this).findParent('li').attr('id'));
			//parent.children(area)
			if (Item.auto_open_dialog)
				tmp/*.dialog(Item.dialog_options)*/.show().find('textarea').each(function (index, item){
					CKEDITOR.replace(item.name, Item.ckeditor_options);
				});
		} else { 
			$('#' + area+ '_'+$(this).findParent('li').attr('id'))
			//parent.children(area)
			//.dialog('close');
			.hie();
		}
		
		var nodes = parent.findParent('li').children('ul').find(type).not(this);
		if ($(this).is(':checked')) {
			nodes.not(':checked').attr('disabled', 'disabled').attr('checked', 'checked');
		} else {
			nodes.filter(":checked").filter(":disabled").removeAttr('checked').removeAttr('disabled');
		}
		
		$(this).findParent('li').find('.dlg_link img').each(function(index, item) {
			var cbs = $(this).findParent('.item').children('.comment_area').find('input[type=checkbox]').filter(':checked');
			Item.set_validation_image($(this), cbs);
		});
		
		/*nodes.findParent('.item').find('.dlg_link img').each(function(index, item) {
			var cbs = $(this).findParent('.item').children('.comment_area').find('input[type=checkbox]').filter(':checked');
			Item.set_validation_image($(this), cbs);
		});*/
	});
};

Item.set_validation_image = function (img, cbs) {
		if (cbs.filter('.adviser_validation').length > 0) {
			img.attr('src', Item.adviser_validation_image).attr('alt', 'Validé par le conseiller');
		} else if (cbs.filter('.owner_validation').length > 0) {
			img.attr('src', Item.owner_validation_image).attr('alt', 'Validé par le porteur');
		} else if (cbs.filter('.objective').length > 0) {
			img.attr('src', Item.objective_image).attr('alt', 'Défini comme objectif');
		} else {
			img.attr('src', Item.comment_image).attr('alt', 'Commentaires');
		}
};

Item.find_first = function (jnode) {
	return jnode.findParent('[id^=step_]');
};

Item.save = function(item) {
	Item.previous[item.id] = item.value;
};

Item.revert = function(item) {
	if (Item.previous[item.id] != null && Item.previous[item.id] != undefined) {
		item.value = Item.previous[item.id];
		Item.previous[item.id] = null;
	}
};

Item.commit = function(item) {
	Item.previous[item.id] = null;
};

jQuery.fn.revertItem = function () {
	return this.each(function (index, item){
		Item.revert(item);
	});
};

jQuery.fn.saveItem = function () {
	return this.each(function (index, item){
		Item.save(item);
	});
};

jQuery.fn.commitItem = function () {
	return this.each(function (index, item){
		if (item.disabled == null || item.disabled == undefined)
			Item.commit(item);
	});
};

jQuery.fn.setStartDate = function(dateStr) {
	var update = true;
	var errors = "";
	var date = DateUtils.parse(Item.dateFormat, dateStr);
	this.each(function (index, item){
		var parent = $(item).findParent('li').filter('[id^=step_]');
		var root = Item.steps.children('.item').children('.cb_select_item').filter('[value=1]').parent().parent();
		/*if (parent.length > 0 && parent[0].id != root[0].id) {
			alert ("Impossible de modifier la date de début d'une étape exceptée la première");
			$(item).revertItem();
			update = false;
			return;
		}*/
		
		var end_date = $(item).parent().children('.end_date').attr('value');
		end_date = DateUtils.parse(Item.dateFormat, end_date);
		if (end_date.getTime() < date.getTime()) {
			errors = errors + " - " + $(item).findParent('li').children('.label').text() + "\n";
			$(item).revertItem();
			update = false;
		}
	});
	
	if (update) {
		this.attr('value', dateStr);
	} else if (errors.length > 0){
		alert("La date ne peut pas être changé sur ces items :\n"+errors+"La date de début est postérieure à celle de fin");
	}
	
	// TODO tous les précédents qui ne sont pas checkés => on décalle de nb
	// jours y compris la sauvegarde.
	// TODO idem pour ses enfants.
	
	return update;
};

jQuery.fn.setEndDate = function(dateStr) {
	var update = true;
	var errors = "";
	var date = DateUtils.parse(Item.dateFormat, dateStr);
	this.each(function (index, item){
// var parent = $(item).findParent('li').filter('[id^=step_]');
// if (parent.length > 0 && parent[0].id != Item.steps[0].id) {
// alert ("Impossible de modifier la date de début d'une étape exceptée la
// première");
// $(item).revertItem();
// update = false;
// return;
// }
		
		var start_date = $(item).parent().children('.start_date').attr('value');
		start_date = DateUtils.parse(Item.dateFormat, start_date);
		if (start_date.getTime() > date.getTime()) {
			errors = errors + " - " +$(item).findParent('li').children(".item").children('.label').text() + "\n";
			$(item).revertItem();
			update = false;
		}
	});
	
	if (update) {
		this.attr('value', dateStr);
	} else if (errors.length > 0){
		alert("La date ne peut pas être changé sur ces items :\n"+errors+"La date de fin est antérieure à celle de début");
	}
	
	return update;
};

jQuery.fn.findParent = function(selector) {
	if(selector == null || selector == undefined) {
		return this.parent();
	}
	
	res = [];
	$(this).each(function (index, item) {
		p = $(item).parent();
		f = p.filter(selector);
		while (p.length > 0 && f.length == 0) {
			p = p.parent();
			f = p.filter(selector);
		}
		
		if (f.length > 0){
			res.push(f[0]);
		}
	});
	res = jQuery.unique(res);
	return this.pushStack(res);
};

jQuery.fn.beforeDate = function(dateStr) {
	if (dateStr == undefined || dateStr == null)
		return (this);
	
	res = [];
	date = DateUtils.parse(Item.dateFormat, dateStr);
	$(this).each(function (index, item) {
		if (item.value != null && item.value != undefined) {
			try {
				d = DateUtils.parse(Item.dateFormat, this.value);
				if (d.getTime() <= date.getTime())
					res.push(this);
			} catch(ex) {
			}
		}
	});
	res = jQuery.unique(res);
	return this.pushStack(res);
};

jQuery.fn.afterDate = function(dateStr) {
	if (dateStr == undefined || dateStr == null)
		return (this);
	
	res = [];
	date = DateUtils.parse(Item.dateFormat, dateStr);
	$(this).each(function (index, item) {
		if (item.value != null && item.value != undefined) {
			try {
				d = DateUtils.parse(Item.dateFormat, this.value);
				if (d.getTime() >= date.getTime())
					res.push(this);
			} catch(ex) {
			}
		}
	});
	res = jQuery.unique(res);
	return this.pushStack(res);
};

jQuery.fn.start_date = function() {
	return this.pushStack(this.children('.item').children('.user_inputs').children('.start_date'));
};

jQuery.fn.end_date = function() {
	return this.pushStack(this.children('.item').children('.user_inputs').children('.end_date'));
};

jQuery.fn.minDate = function(selector, df) {
	var d = null;
	
	this.find(selector).each(function(index, item){
		if (item.value != null && item.value != undefined && (item.disabled == null || item.disabled == undefined || !item.disabled)) {
			try {
				var tmp = DateUtils.parse(df, item.value);
				if (d == null) {
					d = tmp;
				} else if (tmp.getTime() < d.getTime()){
					d = tmp;
				}
			} catch (e) {
			}
		}
	});
	
	if (d == null) d = DateUtils.today();
	
	return DateUtils.format(df, d);
};

jQuery.fn.maxDate = function(selector, df) {
	var d = null;
	
	this.find(selector).each(function(index, item){
		if (item.value != null && item.value != undefined && (item.disabled == null || item.disabled == undefined || !item.disabled)) {
			try {
				var tmp = DateUtils.parse(df, item.value);
				if (d == null) {
					d = tmp;
				} else if (tmp.getTime() > d.getTime()){
					d = tmp;
				}
			} catch (e) {
			}
		}
	});
	
	if (d == null) d = DateUtils.today();
	
	return DateUtils.format(df, d);
};

jQuery.fn.addDays = function (df, nb) {
	return this.each(function(index, item){
		if (item.value != null && item.value != undefined) {
			try {
				var tmp = DateUtils.parse(df, item.value);
				tmp = DateUtils.add(tmp, DateUtils.DAY, nb);
				tmp = DateUtils.format(df, tmp);
				$(this).saveItem().attr('value', tmp);
			} catch (e) {
			}
		}
	});
};

jQuery.fn.unchecked = function(recurse) {
	if (recurse == undefined || recurse == null)
		recurse = true;
	
	if (this.length == 0)
		return this;
	
	var cb = this;
	var id = cb.findParent('li').attr('id');
	Logger.info("["+id+"] On décoche...");
	
	cb.removeClass('checked undetermined').addClass('unchecked');
	cb.siblings('.cb_select_item').attr('value', '0');
	if(recurse) {
		Logger.info("["+id+"] On décoche ses enfants et on désactive les champs date de début et de fin.");
		cb.findParent('li').find('.checkbox').not(cb).filter('.checked, .undetermined')
			.removeClass('checked undetermined').addClass('unchecked')
			.siblings('.cb_select_item').attr('value', '0');
		cb.findParent('li').find ('.start_date, .end_date').attr('disabled', 'disabled').saveItem();
	} else {
		Logger.info("["+id+"] On désactive les champs date de début et de fin.");
		cb.findParent('li').start_date().attr('disabled', 'disabled').saveItem();
		cb.findParent('li').end_date().attr('disabled', 'disabled').saveItem();
	}
	
	// var root =
	// Item.steps.children('.item').children('.cb_select_item').filter('[value=1]').parent().parent();
	var root = cb.findParent('li').filter('[id^=step_]') ;
	if (root.length > 0){
		// on a désactivé une étape. on met comme date min à TOUS les start_date
		// et end_date la sienne.
		var date = root.start_date().attr('value');
		Logger.info("["+id+"] C'est une étape, on désative toutes les dates de début et de fin et on l'affecte à "+date+".");
		root.end_date().attr('disabled', 'disabled').attr('value', date);
		root.find('li').end_date().attr('disabled', 'disabled').attr('value', date);
		root.find('li').start_date().attr('disabled', 'disabled').attr('value', date);
		
		// TODO deplacer les étapes suivantes.
		date = DateUtils.parse(Item.dateFormat, date);
		var old = root.next().start_date().attr('value');
		
		if (old != null && old != undefined && old != "") {
			var old = DateUtils.parse(Item.dateFormat, old);
			var nb = DateUtils.daysDiff(date, old);
			
			if (nb != 0) {
				Logger.info("["+id+"] on décale les étapes suivantes de "+nb+" jours.");
				root.nextAll().find('.start_date, .end_date').addDays(Item.dateFormat, DateUtils.daysDiff(date, old));
			}
		} else {
			Logger.info("["+id+"] c'est la dernière étape. On n'a rien à décaler.");
		}
	} else {
		var date = cb.findParent('li').findParent('li').start_date().attr('value');
		Logger.info("["+id+"] on prend la date de début du parent: "+date+".");
		cb.findParent('li').start_date().attr('disabled', 'disabled').saveItem().attr('value', date);
		cb.findParent('li').end_date().attr('disabled', 'disabled').saveItem().attr('value', date);
	}
	
	return this;
};

jQuery.fn.checked = function(recurse) {
	if (recurse == undefined || recurse == null)
		recurse = true;
	
	if (this.length == 0)
		return this;
	
	var cb = this;
	var id = cb.findParent('li').attr('id');
	var date = cb.findParent('li').start_date().attr('value');
	var old = cb.findParent('li').end_date().attr('value');
	Logger.info("["+id+"] On coche...");
	
	cb.removeClass('undetermined unchecked').addClass('checked');
	cb.siblings('.cb_select_item').attr('value', '1');
	if(recurse) {
		Logger.info("["+id+"] On coche ses enfants et on réactive les champs date de début et de fin.");
		cb.findParent('li').children('ul').find('.checkbox').not(cb).filter('.unchecked, .undetermined')
			.removeClass('undetermined unchecked').addClass('checked')
			.siblings('.cb_select_item').attr('value', '1');
		cb.findParent('li').find('.start_date, .end_date').removeAttr('disabled').revertItem();
	} else {
		Logger.info("["+id+"] On réactive les champs date de début et de fin.");
		cb.findParent('li').start_date().removeAttr('disabled').revertItem();
		cb.findParent('li').end_date().removeAttr('disabled').revertItem();
	}
	
	// var root =
	// Item.steps.children('.item').children('.cb_select_item').filter('[value=1]').parent().parent();
	var root = cb.findParent('li').filter('[id^=step_]') ;
	if (root.length > 0 && date == old){
		// TODO deplacer les étapes suivantes.
		date = DateUtils.parse(Item.dateFormat, date);
		old = cb.findParent('li').end_date().attr('value');
		
		if (old != null && old != undefined && old != "") {
			var old = DateUtils.parse(Item.dateFormat, old);
			var nb = DateUtils.daysDiff(old, date);
			if (nb != 0) {
				Logger.info("["+id+"] on décale les étapes suivantes de "+nb+" jours.");
				root.nextAll().find('.start_date, .end_date').addDays(Item.dateFormat, nb);
			}
		} else {
			Logger.info("["+id+"] c'est la dernière étape. On n'a rien à décaler.");
		}
	} else {
		Logger.info("["+id+"] on réinitialise les dates.");
		cb.findParent('li').start_date().removeAttr('disabled').revertItem();
		cb.findParent('li').end_date().removeAttr('disabled').revertItem();
	}
	
	return this;
};

jQuery.fn.updateState = function () {
	return this.each(function (index, item) {
		cb = $(item);
		
		var hasChecked = cb.findParent('li').find('.checkbox').not(cb).hasClass('checked');
		var hasUnchecked = cb.findParent('li').find('.checkbox').not(cb).hasClass('unchecked');
		var hasUndeterminated = cb.findParent('li').find('.checkbox').not(cb).hasClass('undetermined');
		
		if ((hasChecked && hasUnchecked) || hasUndeterminated) {
			cb.checked(false);
			cb.removeClass('checked unchecked').addClass('undetermined');
			/*
			 * cb.siblings('.cb_select_item').attr('value', '1');
			 * cb.findParent('li').start_date().removeAttr('disabled');
			 * cb.findParent('li').end_date().removeAttr('disabled');
			 */
		} else if (hasChecked) {
			cb.checked(false);
			/*
			 * cb.removeClass('undetermined unchecked').addClass('checked');
			 * cb.siblings('.cb_select_item').attr('value', '1');
			 * cb.findParent('li').start_date().removeAttr('disabled');
			 * cb.findParent('li').end_date().removeAttr('disabled');
			 */
		} else {
			cb.unchecked(false);
			/*
			 * cb.removeClass('undetermined checked').addClass('unchecked');
			 * cb.siblings('.cb_select_item').attr('value', '0');
			 * cb.findParent('li').start_date().attr('disabled', 'disabled');
			 * cb.findParent('li').end_date().attr('disabled', 'disabled');
			 */
		}
		
	});
	
	
};

